package com.mingqijia.gassafety.authority.vcc.provider;

import cn.hutool.http.*;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.gap.cache.redis.RedisCache;


import com.alibaba.fastjson.JSON;
import com.mingqijia.gassafety.authority.vcc.config.VccOauthConfig;
import com.mingqijia.gassafety.authority.vcc.valueobject.VccUserVO;
import com.mingqijia.gassafety.shared.constant.Constants;
import com.mingqijia.gassafety.shared.vcc.VccAuthoritiesProvider;
import com.mingqijia.gassafety.shared.vcc.VccH5ClientConfig;
import com.mingqijia.gassafety.shared.vcc.VccTokenCodeConfig;
import com.mingqijia.gassafety.shared.handler.GlobalAuthenticationException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
@RequiredArgsConstructor
public class VccOauthProvider {

    private final VccOauthConfig vccOauthConfig;
    private final VccTokenCodeConfig vccTokenCodeConfig;
    private final VccH5ClientConfig h5ClientConfig;
    private final VccAuthoritiesProvider vccAuthoritiesProvider;

    @Autowired
    private Environment environment;

    @Autowired
    RedisCache redisCache;

    public VccUserVO genTokenByCode(String code,String clientId) {
        String redirectUri = environment.getProperty("vcc.open-oauth." + clientId + ".redirectUri");
        String oauth = environment.getProperty("vcc.oauth.redirectUri");
        HttpRequest request = HttpUtil.createRequest(Method.POST, vccTokenCodeConfig.getGenTokenUrl(clientId));
        log.info("redirectUri的值为{} oauth返回结果{}，", redirectUri, oauth);
        String openAppSecret = null;
        if (StringUtils.isNotEmpty(redirectUri)) {
            VccTokenCodeConfig codeConfig = new VccTokenCodeConfig();
            codeConfig.setCode(code);
            codeConfig.setRedirectUri(vccOauthConfig.getRedirectUri());
            codeConfig.setRedirectUri(redirectUri);
            String server = environment.getProperty("vcc.open-oauth." + clientId + ".server");
            codeConfig.setServer(server);
            String scope = environment.getProperty("vcc.open-oauth." + clientId + ".scope");
            codeConfig.setScope(scope);
            String grantType = environment.getProperty("vcc.open-oauth." + clientId + ".grantType");
            codeConfig.setGrantType(grantType);
            String openAppId = environment.getProperty("vcc.open-oauth." + clientId + ".openAppId");
            codeConfig.setOpenAppId(openAppId);
            openAppSecret = environment.getProperty("vcc.open-oauth." + clientId + ".openAppSecret");
            codeConfig.setOpenAppSecret(openAppSecret);
            request.body(codeConfig.toJson(), ContentType.JSON.getValue());
        }
        else {
            vccTokenCodeConfig.setCode(code);
            vccTokenCodeConfig.setRedirectUri(vccOauthConfig.getRedirectUri());
            request.body(vccTokenCodeConfig.toJson(), ContentType.JSON.getValue());
        }
        VccUserVO vccUserVO = doHttpVCCRequest(request);
        if (vccUserVO != null) {
            redisCache.setCacheStr(vccUserVO.getToken(), openAppSecret, vccUserVO.getExpireTime(), TimeUnit.SECONDS);
        }
        return vccUserVO;
    }

    public VccUserVO genH5TokenByToken(String token) {
        log.info("h5 token:{}",token);
        Map<String, String> loginUserInfo = vccAuthoritiesProvider.getVccUserInfo(token);
        VccUserVO vccUserVO = new VccUserVO();
        vccUserVO.setPhone(null == loginUserInfo ? null : loginUserInfo.get("phone"));
        vccUserVO.setVccUserId(null == loginUserInfo ? null : loginUserInfo.get("userId"));
        log.info("vccUserVO:{}", JSON.toJSONString(vccUserVO));
        return vccUserVO;
    }

    public VccUserVO refreshToken(String refreshToken) {
        vccTokenCodeConfig.setRefreshToken(refreshToken);
        HttpRequest request = HttpUtil.createRequest(Method.POST, vccTokenCodeConfig.getRefreshTokenUrl());
        request.removeHeader(Header.AUTHORIZATION);
        return doHttpRequest(request);
    }

    public String logout(HttpServletRequest request) throws IOException {
        return vccOauthConfig.getLogoutUrl(request);
    }

    public VccUserVO checkToken(String token) {
        HttpRequest request = HttpUtil.createRequest(Method.POST, vccTokenCodeConfig.getCheckTokenUrl());
        request.header(Header.AUTHORIZATION, buildToken(token));
        return doHttpRequest(request);
    }

    @Nullable
    private VccUserVO doHttpRequest(HttpRequest request) {
        request.body(vccTokenCodeConfig.toJson(), ContentType.JSON.getValue());

        HttpResponse response = request.execute();
        if (!Objects.equals(response.getStatus(), HttpStatus.HTTP_OK)) {
            log.error("请求VCC接口失败{}，request={}, msg={}", request.getUrl(), JSONUtil.toJsonStr(request), response.body());
            throw new GlobalAuthenticationException(Constants.CODE_GAS_AUTH_FAILED, "获取token失败");
        }
        // JSONObject result = JSONUtil.parseObj("{\"code\":\"0\",\"data\":{\"refreshTokenExpiration\":\"604800\",\"openid\":\"8a8ab0b246dc81120146dc8181950052\",\"channelType\":\"web\",\"spId\":\"ae93fdddd22a4fe69cf90f06af71923a\",\"token\":\"eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJvcGVuaWQiOiI4YThhYjBiMjQ2ZGM4MTEyMDE0NmRjODE4MTk1MDA1MiIsImNoYW5uZWxUeXBlIjoid2ViIiwidHlwZSI6ImNybSIsInNwSWQiOiJhZTkzZmRkZGQyMmE0ZmU2OWNmOTBmMDZhZjcxOTIzYSIsImF1dGhvcml0aWVzIjoicmVhZCUyMHdyaXRlIiwib3JnSWQiOiI4YTlhZTdmMDU2ZmUwMjU0MDE1NmZlMjU2NmZiMDAwMSIsInRva2VuIjoiYWZjNWY0N2ZkMGNlNDVmYjhiMjk2MzJlYzcwNzZlOWEiLCJvcGVuQXBwSWQiOiJBTEFSTSIsInJlZnJlc2hfdG9rZW4iOiI3ZWYwMTY2YjRmZDI0NGVkYTVhZGIzMmQwOTQ0ZWU2NSIsImV4cGlyZVRpbWUiOiI2MDQ2MDAiLCJzY29wZSI6InJlYWQlMjB3cml0ZSIsInJlZnJlc2hfdG9rZW5fZXhwaXJhdGlvbiI6IjYwNDgwMCIsInRva2VuVHlwZSI6ImJlYXJlciIsImV4cCI6MTcxNDUzMTM4NCwiaWF0IjoxNzEzOTI2Nzg0fQ.yyI5Kgin9vB708JYrD3ppws4UP7vdz8O8-SqAKPjPRqGbgVAmfjle7TZLUYn1F-8qJ8MMHl4i6I-5-KbwABRWQ\",\"openAppId\":\"ALARM\",\"expireTime\":\"604600\",\"scope\":[\"read%20write\"],\"refreshToken\":\"7ef0166b4fd244eda5adb32d0944ee65\"},\"message\":\"操作成功\"}");
        JSONObject result = JSONUtil.parseObj(response.body());
        log.info("请求VCC业务接口{} 返回结果{}，body={}", request.getUrl(), result, vccTokenCodeConfig.toJson());

        if (!Objects.equals(result.getInt("code"), Constants.INT_ZERO)) {
            log.error("请求VCC业务接口失败{}，msg={}", request.getUrl(), result);
            throw new GlobalAuthenticationException(result.getInt("code"), result.getStr("message"));
        }
        return JSONUtil.toBean(result.getJSONObject("data"), VccUserVO.class);
    }

    @Nullable
    private VccUserVO doHttpVCCRequest(HttpRequest request) {

        HttpResponse response = request.execute();
        if (!Objects.equals(response.getStatus(), HttpStatus.HTTP_OK)) {
            log.error("请求VCC接口失败{}，request={}, msg={}", request.getUrl(), JSONUtil.toJsonStr(request), response.body());
            throw new GlobalAuthenticationException(Constants.CODE_GAS_AUTH_FAILED, "获取token失败");
        }
        JSONObject result = JSONUtil.parseObj(response.body());
        log.info("请求VCC业务接口{} 返回结果{}，body={}", request.getUrl(), result, JSONUtil.toJsonStr(request));

        if (!Objects.equals(result.getInt("code"), Constants.INT_ZERO)) {
            log.error("请求VCC业务接口失败{}，msg={}", request.getUrl(), result);
            throw new GlobalAuthenticationException(result.getInt("code"), result.getStr("message"));
        }
        return JSONUtil.toBean(result.getJSONObject("data"), VccUserVO.class);
    }

    private String buildToken(String token) {
        return token.startsWith(Constants.PREFIX_BEARER) ? token :
                Constants.PREFIX_BEARER + token;
    }
}
